import json
import allure
import pytest
import requests
import urllib3
import time

from conf import setting
from common.recordlog import logs
from requests import utils
from common.readyaml import ReadYamlData
from urllib3.exceptions import InsecureRequestWarning

class SendRequest:
    """
    发送接口请求，暂时只有get和post方法的请求
    """
    def __init__(self,cookie=None):
        self.cookie=cookie
        self.read=ReadYamlData()

    def get(self,url,data,header):
        """
        :param url: 接口地址
        :param data: 请求参数
        :param header: 请求头
        :return:
        """
        requests.packages.urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

        try:
            # 没数据就不传数据
            if data is None:
                response=requests.get(url,headers=header,cookies=self.cookie,verify=False)
            #有数据则传数据
            else:
                response=requests.get(url,data,headers=header,cookies=self.cookie,verify=False)
        except requests.RequestException as e:
            logs.error(e)
            return None
        except Exception as e:
            logs.error(e)
            return None

        #响应时间/毫秒
        res_ms=response.elapsed.microseconds/1000
        #响应时间/秒
        res_second=response.elapsed.total_seconds()
        #创建字典对象（kv）
        response_dict=dict()

        """
        requests.get 方法返回一个 Response 对象，该对象包含服务器返回的数据以及有关响应的各种信息。常用的属性包括：

        response.text: 服务器返回的内容，作为字符串。
        response.content: 服务器返回的内容，作为字节形式。
        response.status_code: HTTP 状态码。
        response.headers: 服务器返回的响应头。
        response.json(): 将响应内容解析为 JSON 格式（假设内容是 JSON 格式的）。
        """
        #接口响应状态码
        response_dict['code']=response.status_code
        #接口响应文本
        response_dict['text']=response.text
        try:
            response_dict['body']=response.json().get('body')
        except Exception:
            response_dict['body']=''

        response_dict['res_ms']=res_ms
        response_dict['res_second']=res_second

        return response_dict

    def post(self,url,data,header):
        """

        :param url:
        :param data: verify=False忽略SSL证书验证
        :param header:
        :return:
        """
        requests.packages.urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

        try:
            # 没数据就不传数据
            if data is None:
                response = requests.post(url, header, cookies=self.cookie, verify=False)
            # 有数据则传数据
            else:
                response = requests.post(url, data, headers=header, cookies=self.cookie, verify=False)
        except requests.RequestException as e:
            logs.error(e)
            return None
        except Exception as e:
            logs.error(e)
            return None

        # 响应时间/毫秒
        res_ms = response.elapsed.microseconds / 1000
        # 响应时间/秒
        res_second = response.elapsed.total_seconds()
        response_dict = dict()

        """
        requests.get 方法返回一个 Response 对象，该对象包含服务器返回的数据以及有关响应的各种信息。常用的属性包括：

        response.text: 服务器返回的内容，作为字符串。
        response.content: 服务器返回的内容，作为字节形式。
        response.status_code: HTTP 状态码。
        response.headers: 服务器返回的响应头。
        response.json(): 将响应内容解析为 JSON 格式（假设内容是 JSON 格式的）。
        """
        # 接口响应状态码
        response_dict['code'] = response.status_code
        # 接口响应文本
        response_dict['text'] = response.text
        try:
            response_dict['body'] = response.json().get('body')
        except Exception:
            response_dict['body'] = ''

        response_dict['res_ms'] = res_ms
        response_dict['res_second'] = res_second

        return response_dict

    def send_request(self,**kwargs):
        """
        :param kwargs:允许调用者灵活地传递请求所需的各种参数（如 method, url, headers, data 等）。
        :return:
        """
        session=requests.session()
        result=None
        # 字典
        cookie={}

        try:
            result=session.request(**kwargs)
            set_cookie=requests.utils.dict_from_cookiejar(result.cookies)
            if set_cookie:
                cookie['Cookie']=set_cookie
                self.read.write_yaml_data(cookie)
                logs.info("cookie:%s"%cookie)
            logs.info("接口返回信息：%s"%result.text if result.text else result)
        except requests.exceptions.ConnectionError:
            logs.error("ConnectionError--连接异常")
            pytest.fail("接口请求异常，可能是request的连接数过多或请求速度过快导致程序报错！")
        except requests.exceptions.HTTPError:
            logs.error("HTTPError--http异常")
        except requests.exceptions.RequestException as e:
            logs.error(e)
            pytest.fail("请求异常，请检查系统或数据是否异常！")

        return result

    def run_main(self,name,url,case_name,header,method,cookies=None,file=None,**kwargs):
        """
        接口请求
        :param name: 接口名
        :param url: 接口地址
        :param case_name: 测试用例
        :param header: 请求头
        :param method: 请求方法
        :param cookies: 默认为空
        :param file: 上传文件接口
        :param kwargs: 请求参数，根据yaml文件（序列化）的参数类型
        :return:
        """
        try:
            # 收集报告日志
            logs.info('接口名称：%s'%name)
            logs.info('请求地址：%s'%url)
            logs.info('请求方法：%s'%method)
            logs.info('测试用例名称：%s'%case_name)
            logs.info('请求头：%s'%header)
            logs.info('Cookie：%s'%cookies)

            req_params=json.dumps(kwargs,ensure_ascii=False)
            if "data" in kwargs.keys():
                allure.attach(req_params,'请求参数',allure.attachment_type.TEXT)
                logs.info("请求参数：%s"%kwargs)
            elif "json" in kwargs.keys():
                allure.attach(req_params, '请求参数', allure.attachment_type.TEXT)
                logs.info("请求参数：%s" % kwargs)
            elif "parama" in kwargs.keys():
                allure.attach(req_params, '请求参数', allure.attachment_type.TEXT)
                logs.info("请求参数：%s" % kwargs)
        except Exception as e:
            logs.error(e)

        requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
        response=self.send_request(method=method,
                                   url=url,
                                   header=header,
                                   cookies=cookies,
                                   files=file,
                                   timeout=setting.API_TIMEOUT,
                                   verify=False,
                                   **kwargs)
        return response
